package JasPerl::Util::Date;

use 5.010;
use strict;
use warnings;

use JasPerl::Util::Exceptions;

use Scalar::Util qw(blessed);
use Time::HiRes;
use Time::Piece;

use constant FMT => '%a %b %d %T %Z %Y';

my %COERCIONS = (
    'Time::Piece' => sub {
        my ($class, $from) = @_;
        my $time = int($from->epoch * 1000);
        return $class->JasPerl::Util::Date::new($time);
    },
    'DateTime' => sub {
        my ($class, $from) = @_;
        my $time = int($from->hires_epoch * 1000);
        return $class->JasPerl::Util::Date::new($time);
    }
);

sub new {
    my ($class, $time) = @_;
    $time //= int(Time::HiRes::time() * 1000);
    bless \$time, $class;
}

sub from {
    my ($class, $from) = @_;
    return unless defined $from;

    if (blessed $from) {
        return $from if $from->isa($class);

        foreach my $type (keys %COERCIONS) {
            return $COERCIONS{$type}->($class, $from) if $from->isa($type);
        }
    }

    JasPerl::Util::CoercionException->throw(
        "Cannot create $class from " . (ref $from || 'scalar')
    );
}

sub clone {
    bless \${$_[0]}, ref $_[0];
}

sub get_time {
    return ${$_[0]};
}

sub set_time {
    ${$_[0]} = $_[1];
}

sub as_epoch {
    return int($_[0]->get_time() / 1000);
}

sub as_gmtime {
    return gmtime $_[0]->as_epoch;
}

sub as_localtime {
    return localtime $_[0]->as_epoch;
}

sub as_string {
    return $_[0]->as_localtime->strftime(FMT);
}

use overload (
    '""' => 'as_string'
);

1;
